package com.flashcash.solu.app.base;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;

import com.alibaba.android.arouter.launcher.ARouter;
import com.facebook.accountkit.AccountKitError;
import com.facebook.accountkit.AccountKitLoginResult;
import com.flashcash.kotlin.activity.InfoFillActivity;
import com.flashcash.kotlin.activity.LoginSwitcher;
import com.flashcash.kotlin.auth.accountKit.AccountKitLoginManager;
import com.flashcash.kotlin.auth.accountKit.LoginEventBus;
import com.flashcash.solu.BuildConfig;
import com.flashcash.solu.R;
import com.flashcash.solu.app.App;
import com.flashcash.solu.app.base.presenter.BaseActivityPresenter;
import com.flashcash.solu.bean.ProgressBean;
import com.flashcash.solu.common.EventCollection;
import com.flashcash.solu.common.FieldParams;
import com.flashcash.solu.common.TokenManager;
import com.flashcash.solu.utils.ACache;
import com.flashcash.solu.view.SplashActivity;
import com.flashcash.solu.view.certification.ContactInfoActivity;
import com.flashcash.solu.view.certification.PersonalInfoActivity;
import com.flashcash.solu.view.certification.ProfessionalInfoActivity;
import com.flashcash.solu.widget.MyProgressBar;
import com.flashcash.solu.widget.xleotoast.XLeoToast;
import com.hwangjr.rxbus.RxBus;
import com.trello.rxlifecycle.LifecycleProvider;
import com.trello.rxlifecycle.LifecycleTransformer;
import com.trello.rxlifecycle.RxLifecycle;
import com.trello.rxlifecycle.android.ActivityEvent;
import com.trello.rxlifecycle.android.RxLifecycleAndroid;
import com.x.leo.apphelper.log.XLog;
import com.x.leo.apphelper.utils.AndroidBug5497Workaround;

import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Field;

import javax.annotation.Nonnull;

import butterknife.ButterKnife;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import rx.subjects.BehaviorSubject;

public abstract class BaseActivity<T extends BaseActivityPresenter> extends FragmentActivity implements LifecycleProvider<ActivityEvent>, BaseActivityView {
    private static final int LOGIN_INTERCEPT = 1005;
    protected final String TAG = this.getClass().getSimpleName();
    public T mPresenter;
    protected Context context;


    @Override
    public BaseActivity getBaseActivity() {
        return this;
    }

    private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.lifecycleSubject.onNext(ActivityEvent.CREATE);
        mPresenter = initPresenterImpl();
        mPresenter.attach(this);
        if (!(this instanceof SplashActivity)) {
            setTheme(R.style.AppTheme);
        }
        //设置竖屏
        if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
        initBeforeSetContentView();
        context = this;
        if (/*!(this instanceof SplashActivity) && */getLayoutResId() != -1) {
            setContentView(getLayoutResId());
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//设置状态栏字段颜色为灰色
            getBaseActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }

        ARouter.getInstance().inject(this);
        ButterKnife.bind(this);
        init();


    }

    protected abstract int getLayoutResId();

    protected abstract void init();

    protected void initBeforeSetContentView() {
    }

    protected abstract T initPresenterImpl();


    @Override
    protected void onStart() {
        super.onStart();
        this.lifecycleSubject.onNext(ActivityEvent.START);
        AndroidBug5497Workaround.assistActivity(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        this.lifecycleSubject.onNext(ActivityEvent.RESUME);
        App.instance.setCurrentActivity(this);
    }

    protected ActivityEvent getCurrentActivityState() {
        return lifecycleSubject.getValue();
    }

    public boolean isActive() {
        ActivityEvent currentActivityState = getCurrentActivityState();
        return currentActivityState != null && currentActivityState.ordinal() >= 0 && currentActivityState.ordinal() < 5;
    }

    /**
     * @param destContext 上下文对象
     *                    用于解决输入法内存泄露
     */
    public static void fixInputMethodManagerLeak(Context destContext) {
        if (destContext == null) {
            return;
        }

        InputMethodManager imm = (InputMethodManager) destContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null) {
            return;
        }

        String[] arr = new String[]{"mCurRootView", "mServedView", "mNextServedView"};
        Field f;
        Object obj_get;
        for (String param : arr) {
            try {
                f = imm.getClass().getDeclaredField(param);
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                obj_get = f.get(imm);
                if (obj_get != null && obj_get instanceof View) {
                    View v_get = (View) obj_get;
                    if (v_get.getContext() == destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的
                        f.set(imm, null); // 置空，破坏掉path to gc节点
                    } else {
                        // 不是想要目标销毁的，即为又进了另一层界面了，不要处理，避免影响原逻辑,也就不用继续for循环了
                        break;
                    }
                }
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }

    @Override
    protected void onPause() {
        this.lifecycleSubject.onNext(ActivityEvent.PAUSE);
        hideSoftSpan();

        clearReferences();
        super.onPause();
    }

    @Override
    protected void onStop() {
        this.lifecycleSubject.onNext(ActivityEvent.STOP);
        super.onStop();
        AndroidBug5497Workaround.deassistActivity(this);
    }

    @Override
    protected void onDestroy() {
        this.lifecycleSubject.onNext(ActivityEvent.DESTROY);
        mPresenter.disAttach();
        mPresenter = null;
        if (isDialogShowing()) {
            dismissLoading();
        }
        fixInputMethodManagerLeak(this);
        clearReferences();
        super.onDestroy();
    }

    private void clearReferences() {
        if (this.equals(App.instance.getCurrentActivity()))
            App.instance.setCurrentActivity(null);
    }

    @Nonnull
    @Override
    public Observable<ActivityEvent> lifecycle() {
        return this.lifecycleSubject.asObservable();
    }

    @Nonnull
    @Override
    public <X> LifecycleTransformer<X> bindUntilEvent(@Nonnull ActivityEvent event) {
        return RxLifecycle.bindUntilEvent(this.lifecycleSubject, event);
    }

    @Nonnull
    @Override
    public <X> LifecycleTransformer<X> bindToLifecycle() {
        return RxLifecycleAndroid.bindActivity(this.lifecycleSubject);
    }

    public <X> Observable.Transformer<X, X> applySchedulers() {
        return new Observable.Transformer<X, X>() {

            @Override
            public Observable<X> call(Observable<X> tObservable) {
                return tObservable
                        .unsubscribeOn(Schedulers.io())
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // RegionLevel you specify a parent activity in AndroidManifest.xml.
        if (item.getItemId() == android.R.id.home) {
            finish();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void changeTo(Class cls) {
        changeTo(cls, null);

    }

    public void changeToForResult(Class cls, int requestCode) {
        changeToForResult(cls, requestCode, false);
    }

    public void changeToForResult(Class cls, int requestCode, boolean checkLogin) {
        Intent intent = new Intent(this, cls);
        if (checkLogin && !isLogin()) {
            intent.putExtra(FieldParams.REQUEST_CODE, requestCode);
            changeTo(intent, true);
        } else {
            startActivityForResult(intent, requestCode);
        }
    }

    public void changeTo(Class cls, Bundle b) {

        Intent i = new Intent(this, cls);
        if (b != null) {
            i.putExtras(b);
        }
        startActivity(i);

    }

    public void changeTo(Class cls, String paramKey, Parcelable p) {
        Bundle b = new Bundle();
        b.putParcelable(paramKey, p);
        changeTo(cls, b);
    }


    /**
     * 检查登录状态的跳转，登录则跳转，否则留在本页
     *
     * @param intent     跳转意图
     * @param checkLogin 是否检查登录状态
     */
    public void changeTo(Intent intent, boolean checkLogin) {
        if (checkLogin) {
            if (!isLogin()) {
                Intent loginIntent = getLoginIntent(this);
                loginIntent.putExtra(FieldParams.TEMP_INTENT, intent);
                startActivityForResult(loginIntent, LOGIN_FACEBOOK_ACCOUNT_KIT);
            } else {
                startActivity(intent);
            }
        } else {
            startActivity(intent);
        }

    }

    public static final int LOGIN_FACEBOOK_ACCOUNT_KIT = 0x1f23;

    @NonNull
    public static Intent getLoginIntent(final BaseActivity act) {
//        return new Intent(this, LoginActivity.class);
//        return new Intent(context.getApplicationContext(), LoginSwitcher.class);
        AccountKitLoginManager.INSTANCE.setCallBack(new AccountKitLoginManager.CallBack() {
            @Override
            public void onError(@org.jetbrains.annotations.Nullable AccountKitError error) {
                AccountKitLoginManager.INSTANCE.setCallBack(null);
                XLog.INSTANCE.i("error:" + (error != null ? error.toString() : ""), 10);
            }

            @Override
            public void onSuccess(@NotNull AccountKitLoginResult loginResult) {

                String authorizationCode = loginResult.getAuthorizationCode();
                if (authorizationCode != null) {
                    AccountKitLoginManager.INSTANCE.setCallBack(null);
                    XLog.INSTANCE.i(authorizationCode, 10);
                    if (act.mPresenter != null) {
                        act.mPresenter.loginByAccountKit(authorizationCode);
                    }

                } else {
                    XLeoToast.showMessage(R.string.obtain_account_kit_auth_code_error);
                }
            }

            @Override
            public void onCancel(@NotNull AccountKitLoginResult loginResult) {
                AccountKitLoginManager.INSTANCE.setCallBack(null);
                AccountKitLoginManager.INSTANCE.unbindAccountKitStateListener(act);
                XLog.INSTANCE.i("cancel", 10);
            }
        });

        return AccountKitLoginManager.INSTANCE.phoneLogin(act);
    }

    private void hideSoftSpan() {
        try {
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            if (imm == null) {
                return;
            }
            String[] arr = new String[]{"mServedView", "mNextServedView", "mCurRootView"};
            Field f;
            Object obj_get;
            for (String param : arr) {
                f = imm.getClass().getDeclaredField(param);
                if (f == null) {
                    continue;
                }
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                obj_get = f.get(imm);
                if (obj_get != null && obj_get instanceof View) {
                    View v_get = (View) obj_get;
                    imm.hideSoftInputFromWindow(v_get.getWindowToken(), 0);
                }
            }
        } catch (Exception e) {
            XLog.INSTANCE.e("hide soft span error:" + e.getMessage(), e, 100);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);


        if (requestCode == LOGIN_INTERCEPT) {
            if (isLogin() && data != null) {
                //XLeoToast.showMessage("reskip");
                AccountKitLoginManager.INSTANCE.handleResult(data, this);
                Intent newIntent = data.getParcelableExtra(FieldParams.TEMP_INTENT);
                int requestCode2 = newIntent.getIntExtra(FieldParams.REQUEST_CODE, -100);
                if (requestCode2 == -100) {
                    startActivity(newIntent);
                } else {
                    startActivityForResult(newIntent, requestCode2);
                }
            } else {
                XLeoToast.showMessage(R.string.show_not_login_yet);
            }
        } else if (requestCode == LOGIN_FACEBOOK_ACCOUNT_KIT && data != null) {
            // login procedure
            // 1. configure facebook login configuration in AccountKitLoginManager.phoneLogin
            // 2. start the activity configured in step 1
            // 3. wait for activity result of 2. When the result arrives, i.e. onActivityResult, we get a facebook auth code
            // the current step: 4. use the auth code to verify it against our server, which issues a token
            // 4. the current class (view)'s onLoginSuccess & onLoginFail is called
            AccountKitLoginManager.INSTANCE.handleResult(data, this);
        }
    }


    public boolean isLogin() {
        String token = TokenManager.getInstance().getToken();
        return !TextUtils.isEmpty(token);
    }

    MyProgressBar progressDialog;

    public void showLoading(String tag) {
        if (progressDialog == null) {
            progressDialog = new MyProgressBar(context);
        }
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }
    }

    public boolean isDialogShowing() {
        return progressDialog != null && progressDialog.isShowing();
    }


    public void dismissLoading() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

    public String getStringById(int id) {
        return getResources().getText(id).toString();
    }

    public void toLogin() {
        if (BuildConfig.DEBUG || (TextUtils.equals(BuildConfig.FLAVOR, "pinjamanmud_test"))) {
            startActivity(new Intent(getApplicationContext(), LoginSwitcher.class));
        } else {
            AccountKitLoginManager.INSTANCE.bindAccountKitStateListener(this);
            startActivityForResult(getLoginIntent(this), LOGIN_FACEBOOK_ACCOUNT_KIT);
        }

    }

    @Override
    public void onLoginError(Throwable e) {
        XLeoToast.showMessage(getString(R.string.error_occured));
        // notify LoginInterceptor
        runOnUiThread(() -> LoginEventBus.INSTANCE.postFail(e));
    }

    @Override
    public void onLoginSuccess() {
        // notify LoginInterceptor
        runOnUiThread(() ->
                {
                    RxBus.get().post(new EventCollection.LoginSuccess());
                    LoginEventBus.INSTANCE.postSuccess();
                }
        );
    }

    /**
     * 处理资料填完状态
     *
     * @param progressBean
     */
    protected void handlerUnFinishCertify(ProgressBean progressBean, boolean fromSplash) {
        //判断第一步是否完成
        boolean first = false;
        boolean isFilePart = false;
        if (progressBean.isPersonalInfoPart()) {//第二步完成，则第一步一定完成
            first = true;
        } else {//第二步未完成
            if (progressBean.isFilePart()) {//已上传工作照
                ACache aCache = ACache.get(context);
                if ("1".equals(aCache.getAsString(FieldParams.ACacheKeys.ACACHE_FINISH_IDENTIFY))) {//已完成
                    first = true;
                }
                isFilePart = true;
            }
        }

        Intent intent = new Intent(this, InfoFillActivity.class);
        if (!first) {//跳转到第一步
            intent = new Intent(this, InfoFillActivity.class);
            intent.putExtra(FieldParams.INFO_NO, 0);
        } else if (!progressBean.isPersonalInfoPart()) {//第二步
            intent = new Intent(this, PersonalInfoActivity.class);
        } else if (!progressBean.isContactPart()) {//第三步
            intent = new Intent(this, ContactInfoActivity.class);
        } else if (!progressBean.isEmploymentPart()) {//第四步
            intent = new Intent(this, ProfessionalInfoActivity.class);
        }
        if (fromSplash) {
            intent.putExtra(FieldParams.FROM_SPLASH, true);
        }
        intent.putExtra(FieldParams.NOT_FINISH_CERTIFY, true);
        intent.putExtra(FieldParams.NEED_OBTAIN_DATA, isFilePart);
        startActivity(intent);
    }

}
